home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Toolbox / Visual Basic Toolbox (P.I.E.)(1996).ISO / sorting / sortcoll / sortcoll.cls < prev    next >
Text File  |  1995-12-30  |  9KB  |  288 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "SortedCollection"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. '=================================================
  9. 'SortedCollection class for Visual Basic
  10. '--------------------------------------------------------------------------------------
  11. '12/28/95
  12. 'SortedCollection class description.
  13. '
  14. 'I have found this to be a most useful class for writing
  15. 'database apps in VB 4.0.  The key value for the members of
  16. 'a SortedCollection class actually form a searchable index,
  17. 'unlike the unsorted key values of the generic Collection
  18. 'object.  The only catch is that you *must* specify a key for
  19. 'each member.  SortedCollection is lenient and will accept
  20. 'objects and variables of any type - the details are left to the
  21. 'programmer.
  22. '
  23. 'Also, you must explicitly use the Item method to retrieve items
  24. 'from the SortedCollection.  The following will not work:
  25. '
  26. '   Dim MySortList as SortedCollection
  27. '       .
  28. '       .
  29. '       .
  30. '   SomeVariable = MySortList(1).SomeProperty   'wont work
  31. '   SomeVariable = MySortList.Item(1).SomeProperty 'works
  32. '
  33. 'SortedCollection also has two new helpful methods: Key(V) and
  34. 'IndexOf(V).  Key(V) will return the key name for the item at
  35. 'the Vth position (or redundantly, returns Key itself if V is a
  36. 'string).  IndexOf will return the position of the item whose
  37. 'key is V.
  38. '
  39. 'Example:
  40. '   MySortList.Add SomeObject, Object.Name
  41. '   Debug.Print MySortList.IndexOf(Object.Name)  'gives new position
  42. '
  43. '   Debug.Print MySortList.Key(MySortList.Count) 'gives key of last
  44. '                                               'item in collection
  45. '
  46. 'Please note that the key is stored in ALLCAPS, and you
  47. 'cannot add keys 'german' and 'German' to the same SortedCollection.
  48. 'Note that if you use numbers as keys, 100 comes before 20 in the keys
  49. 'since the sort is alphabetic, not numeric.  If this is a problem, you
  50. 'may want to change the default behavior programmatically.
  51. '
  52. 'How do we deal with duplicate index values?  The ErrorAction property, which
  53. 'may be set at runtime, controls the action taken when the user tries to add an
  54. 'item to the collection.  By default, it raises the error before VBA does.  If you set the
  55. 'ErrorAction to ERRACTION_INFORM, SortedCollection will post a message box
  56. 'telling the user that it will not accept the new item.  ERRACTION_IGNORE will pass
  57. 'over the attempted addition, and ERRACTION_REPLACE will replace the old
  58. 'item at that position with the new one.
  59. '
  60. 'Of course, you can always test to see if a key is already in use by the SortedCollection.
  61. 'If IndexOf(SomeKey) = 0, then it is OK to add the new item to the SortedCollection,
  62. 'Alternatively, I have provided a simple wrapper to improve readability in the
  63. 'calling procedure: KeyInUse()
  64. '
  65. 'I order to simplify my class, SortedCollection encapsulates two
  66. 'Collections, one which holds the actual objects in the
  67. 'collection, and one which redundantly holds the indexes as
  68. 'objects.  Since VB does not provide an easy way to retrieve the
  69. 'key value from a particular position, the synchronized key
  70. 'collection allows easy retrieval.
  71. '
  72. 'I'm sure there are many improvements and additions which could be made
  73. 'to this crude SortedCollection class.  I would like to hear from you.
  74. 'You may use the code in this class for free, and the author makes no
  75. 'warranty as to its safety or suitability for any purpose whatsoever.
  76. 'You may send improvements, suggestions and additions to:
  77. '
  78. 'Chris Velazquez
  79. '74073.1566@compuserve.com
  80.  
  81. Option Explicit
  82. Private prvCollection As Collection
  83. Private prvSynchro As Collection
  84. Private prvDuplicateIndexErrorAction As Long
  85.  
  86. Const ERR_DUPINDEX = 457
  87. Const ERR_METHOD_NOT_APPLIC = 438
  88.  
  89. Const ERRACTION_MIN = 0
  90. Const ERRACTION_RAISE = 0              'default (and safest!)
  91. Const ERRACTION_INFORM = 1
  92. Const ERRACTION_IGNORE = 2
  93. Const ERRACTION_REPLACE = 3
  94. Const ERRACTION_MAX = 3
  95. '
  96. '
  97.  
  98. Public Sub Add(V As Variant, K As Variant)     'Key not optional!!!
  99.  
  100. Dim NewKey As String
  101. Dim NewSynchroItem As String
  102. Dim Hi, Lo, Center As Variant
  103.  
  104.    NewSynchroItem = CStr(K)
  105.    NewKey = UCase(NewSynchroItem)
  106.    
  107.    Select Case Count
  108.    
  109.       Case 0
  110.          prvCollection.Add V, NewKey
  111.          prvSynchro.Add NewSynchroItem, NewKey
  112.          
  113.       Case 1
  114.          If Key(1) > NewKey Then
  115.             prvCollection.Add Item:=V, Key:=NewKey, Before:=1
  116.             prvSynchro.Add Item:=NewSynchroItem, Key:=NewKey, Before:=1
  117.             
  118.          ElseIf Key(1) < NewKey Then
  119.             prvCollection.Add Item:=V, Key:=NewKey, After:=Count
  120.             prvSynchro.Add Item:=NewSynchroItem, Key:=NewKey, After:=1
  121.             
  122.          Else
  123.             HandleDuplicateIndex V, K
  124.             Exit Sub
  125.             
  126.          End If
  127.          
  128.       Case Else
  129.          Hi = Count
  130.          Lo = 1
  131.          
  132.          If Key(Lo) > NewKey Then                                               'add to beginning
  133.             prvCollection.Add Item:=V, Key:=NewKey, Before:=1
  134.             prvSynchro.Add Item:=NewSynchroItem, Key:=NewKey, Before:=1
  135.             
  136.          ElseIf Key(Hi) < NewKey Then                                         'add to end
  137.             prvCollection.Add Item:=V, Key:=NewKey, After:=Count
  138.             prvSynchro.Add Item:=NewSynchroItem, Key:=NewKey, After:=Hi
  139.             
  140.          Else                                                                                  'play Hi-Lo
  141.          
  142.             Do Until Hi = Lo + 1
  143.                Center = (Hi + Lo) \ 2               'this rounds instead of truncates
  144.                Select Case Key(Center)
  145.                
  146.                   Case NewKey
  147.                      HandleDuplicateIndex V, K
  148.                      Exit Sub
  149.                      
  150.                   Case Is < NewKey
  151.                      Lo = Center
  152.                      
  153.                   Case Is > NewKey
  154.                      Hi = Center
  155.                      
  156.                End Select
  157.             Loop
  158.             
  159.             If K = Key(Hi) Or K = Key(Lo) Then
  160.                HandleDuplicateIndex V, K
  161.             Else
  162.                prvCollection.Add Item:=V, Key:=NewKey, Before:=Hi
  163.                prvSynchro.Add Item:=NewSynchroItem, Key:=NewKey, Before:=Hi
  164.             End If
  165.          End If
  166.          
  167.       'end of cases
  168.    End Select
  169. End Sub
  170.  
  171. Public Sub Remove(V)
  172.    prvCollection.Remove V
  173.    prvSynchro.Remove V
  174. End Sub
  175.  
  176. Public Function Count()
  177.    Count = prvCollection.Count
  178. End Function
  179.  
  180. Public Function Item(V As Variant) As Variant
  181. On Local Error Resume Next
  182.    Item = prvCollection.Item(V)                              'works only for variables
  183.    If Err = ERR_METHOD_NOT_APPLIC Then
  184.       Set Item = prvCollection.Item(V)                     'works only for objects
  185.    Else
  186.       Err.Raise Err.Number
  187.    End If
  188. End Function
  189.  
  190. Private Sub Class_Initialize()
  191.    Set prvCollection = New Collection
  192.    Set prvSynchro = New Collection
  193. End Sub
  194.  
  195. Public Function Key(V)
  196.    Key = UCase(prvSynchro.Item(V))
  197. End Function
  198.  
  199. Public Function KeyMixedCase(V)
  200.    KeyMixedCase = prvSynchro.Item(V)
  201. End Function
  202.  
  203. Public Sub Clear()
  204.    Do Until Count = 0
  205.       Remove 1
  206.    Loop
  207. End Sub
  208.  
  209. Public Function IndexOf(V)
  210. Dim SearchKey As String
  211. Dim Hi, Lo, Center
  212.  
  213. 'Caution: using Key(IndexOf(blah)) may set up a recursion!
  214.    SearchKey = UCase(V)
  215.    If Count = 0 Then
  216.       IndexOf = 0: Exit Function
  217.       
  218.    Else
  219.       Lo = 1
  220.       Hi = Count
  221.       
  222.       If SearchKey = Key(Hi) Then
  223.          IndexOf = Hi: Exit Function
  224.       ElseIf SearchKey = Key(Lo) Then
  225.          IndexOf = Lo: Exit Function
  226.       Else
  227.          Do Until Hi <= Lo + 1
  228.                Center = (Hi + Lo) \ 2
  229.                Select Case SearchKey
  230.                   Case Key(Center)
  231.                      IndexOf = Center: Exit Function
  232.                   Case Is < Key(Center)
  233.                      Hi = Center
  234.                   Case Is > Key(Center)
  235.                      Lo = Center
  236.                End Select
  237.          Loop                            '(Hi <= Lo + 1)
  238.       
  239.       End If          '(SearchKey)
  240.       
  241.       If SearchKey = Key(Hi) Then
  242.          IndexOf = Hi
  243.       ElseIf SearchKey = Key(Lo) Then
  244.          IndexOf = Lo
  245.       Else
  246.          IndexOf = 0
  247.       End If
  248.       
  249.    End If    '(Count = 0)
  250. End Function
  251.  
  252. Public Property Get ErrorAction() As Integer
  253.    ErrorAction = prvDuplicateIndexErrorAction
  254. End Property
  255.  
  256. Public Property Let ErrorAction(I As Integer)
  257.    If I < ERRACTION_MIN Or I > ERRACTION_MAX Then
  258.       MsgBox "SortedCollection.ErrorAction -- Invalid property value"
  259.    Else
  260.       prvDuplicateIndexErrorAction = I
  261.    End If
  262. End Property
  263.  
  264. Private Sub HandleDuplicateIndex(V As Variant, K As Variant)
  265.  
  266.    Select Case prvDuplicateIndexErrorAction
  267.    
  268.       Case ERRACTION_RAISE
  269.          Err.Raise ERR_DUPINDEX
  270.          
  271.       Case ERRACTION_INFORM
  272.          MsgBox "The key '" & CStr(K) & "' is already in use; cannot add item"
  273.          
  274.       Case ERRACTION_IGNORE
  275.          'Do nothing
  276.          
  277.       Case ERRACTION_REPLACE
  278.          Remove K
  279.          Add V, K
  280.          
  281.    End Select
  282.    
  283. End Sub
  284.  
  285. Public Function KeyInUse(V) As Boolean
  286.    KeyInUse = Not (IndexOf(V) = 0)
  287. End Function
  288.